/*
 *   Copyright 2012, Thomas Kerber
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package milk.jpatch.attribs;

import java.util.List;

import milk.jpatch.CPoolMap;

import org.apache.bcel.classfile.Attribute;

/**
 * Denotes the removal of an attribute type.
 * @author Thomas Kerer
 * @version 1.0.1
 */
public class RemoveAttributeTypePatch extends AttributePatch{
    
    private static final long serialVersionUID = -3391555646432381680L;
    
    /**
     * The attribute types to remove.
     * 
     * No, this isn't final. Yes, you can add your own.
     */
    public static String[] REMOVE_TYPES = new String[]{
        "LineNumberTable",
        "StackMapTable",
        "LocalVariableTable",
        "LocalVariableTypeTable",
        "SourceDebugExtension"
    };
    
    /**
     * The type to be removed.
     */
    private final String typeName;
    
    /**
     * Creates.
     * @param typeName The type to be removed.
     */
    public RemoveAttributeTypePatch(String typeName){
        this.typeName = typeName;
    }
    
    /**
     * Generates.
     * @param old The old attributes.
     * @param new_ The new attributes.
     * @param patches The previously generated patches.
     */
    public static void generate(Attribute[] old, Attribute[] new_,
            List<AttributePatch> patches){
        outer:
        for(Attribute a : old){
            for(Attribute newA : new_){
                if(newA.getName().equals(a.getName()))
                    continue outer;
            }
            patches.add(new RemoveAttributeTypePatch(a.getName()));
        }
        
        /*
         * These get removed no matter what, as they:
         * 
         * a) Serve no semantic purpose at runtime.
         * b) Can cause otherwise working patches to fail verifications
         * c) Can make debugging fuzzy as it is unclear what code is from where.
         */
        for(String name : REMOVE_TYPES)
            patches.add(new RemoveAttributeTypePatch(name));
        
    }
    
    /**
     * 
     * @return The name of the type to be removed.
     */
    public String getName(){
        return typeName;
    }
    
    @Override
    public List<Attribute> patch(List<Attribute> attribs, CPoolMap map){
        return replaceTypeWith(attribs, typeName, null);
    }
    
}
